﻿using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.Practices.Unity.InterceptionExtension;

namespace TSharp.Core.Aop.Handler
{
    /// <summary>
    /// 验证方法中参数不为null的处理类
    /// </summary>
    public class NotNullHandler : ICallHandler
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="NotNullHandler"/> class.
        /// </summary>
        /// <param name="parameterName">Name of the parameter.</param>
        /// <param name="order">The order.</param>
        public NotNullHandler(IList<string> parameterName, int order)
        {
            ParameterName = parameterName;
            Order = order;
        }

        /// <summary>
        /// 不为空的参数名
        /// </summary>
        public IList<string> ParameterName { get; set; }

        #region ICallHandler Members

        /// <summary>
        /// Order in which the handler will be executed
        /// </summary>
        /// <value></value>
        public int Order { get; set; }

        /// <summary>
        /// Implement this method to execute your handler processing.
        /// </summary>
        /// <param name="input">Inputs to the current call to the target.</param>
        /// <param name="getNext">Delegate to execute to get the next delegate in the handler
        /// chain.</param>
        /// <returns>Return value from the target.</returns>
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            for (int i = 0; i < input.Inputs.Count; i++)
            {
                object target = input.Inputs[i];
                if (target == null)
                {
                    ParameterInfo parameterInfo = input.Inputs.GetParameterInfo(i);
                    if (ParameterName == null || ParameterName.Count == 0)
                    {
                        var ex = new ArgumentNullException(parameterInfo.Name);
                        return input.CreateExceptionMethodReturn(ex);
                    }
                    else
                    {
                        foreach (string name in ParameterName)
                        {
                            if (parameterInfo.Name == name)
                            {
                                var ex = new ArgumentNullException(parameterInfo.Name);
                                return input.CreateExceptionMethodReturn(ex);
                            }
                        }
                    }
                }
            }
            return getNext()(input, getNext);
        }

        #endregion
    }
}